Passed
Push — master ( 67261f...67f253 )
by Miloš
02:58
created

BaseAuthService   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 214
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 22
eloc 171
dl 0
loc 214
rs 10
c 0
b 0
f 0

13 Functions

Rating   Name   Duplication   Size   Complexity  
A redirectAfterLogin 0 5 2
A signInAnonymously 0 11 1
A signOut 0 15 3
A signInViaEmail 0 11 1
A signInByProvider 0 21 3
A redirectAfterSignOut 0 4 2
A signInViaTwitter 0 11 1
A subscribeUserChanges 0 19 4
A updateUserData 0 5 1
A signInViaGoogle 0 11 1
A signInViaGithub 0 11 1
A signInViaFacebook 0 11 1
A signInViaPhone 0 11 1
1
import { Injectable } from "@angular/core";
2
import { AngularFireAuth } from "@angular/fire/auth";
3
import { Router } from "@angular/router";
4
import { Platform } from "@ionic/angular";
5
import { auth as firebaseAuth, User as FirebaseUser } from "firebase";
6
import { auth } from "firebase/app";
7
import { BehaviorSubject, Observable, Subscription } from "rxjs";
8
import { UniFirebaseLoginConfig } from "../config/uni-firebase-login-config";
9
import { UniFirebaseLoginConfigProvider } from "../config/uni-firebase-login-config-provider";
10
import { UserModel } from "../model/user-model";
11
import { AuthProvider } from "../providers/auth-provider";
12
import { IAuthProvider } from "../providers/i-auth-provider";
13
import { AuthStorageProvider } from "../storage/auth-storage-provider.service";
14
import { IAuthService } from "./i-auth-service";
15
16
@Injectable({
17
    providedIn: "root",
18
})
19
export class BaseAuthService<User extends UserModel = UserModel>
20
    implements IAuthService {
21
    public get user(): User | null {
22
        return this._user.getValue();
23
    }
24
25
    public get user$(): Observable<User | null> {
26
        return this._user;
27
    }
28
29
    public get userInitialized(): boolean {
30
        return this._userInitialized.getValue();
31
    }
32
33
    public get userInitialized$(): Observable<boolean> {
34
        return this._userInitialized;
35
    }
36
37
    public get currentFirebaseUser(): FirebaseUser | null {
38
        return firebaseAuth().currentUser;
39
    }
40
41
    protected config: UniFirebaseLoginConfig;
42
    protected _user: BehaviorSubject<User | null> = new BehaviorSubject<User | null>(
43
        null,
44
    );
45
    protected _userInitialized: BehaviorSubject<boolean> = new BehaviorSubject<
46
        boolean
47
    >(false);
48
    private userDataSubscription: Subscription | undefined;
49
50
    public constructor(
51
        protected router: Router,
52
        protected platform: Platform,
53
        protected authProvider: AuthProvider,
54
        protected authStorageProvider: AuthStorageProvider<User>,
55
        protected angularFireAuth: AngularFireAuth,
56
        configProvider: UniFirebaseLoginConfigProvider,
57
    ) {
58
        this.config = configProvider.config;
59
        this.subscribeUserChanges();
60
    }
61
62
    public async signInByProvider(
63
        provider: IAuthProvider,
64
        redirect: boolean = true,
65
        callbackBeforeRedirect: (
66
            credential: auth.UserCredential | null,
67
        ) => Promise<void> | void = () => undefined,
68
    ): Promise<void> {
69
        const credential = await provider.handleLogin();
70
        if (
71
            this.config.storage !== false &&
72
            credential &&
73
            credential.user !== null
74
        ) {
75
            await this.authStorageProvider
76
                .getProvider()
77
                .updateStoredDataByFirebaseUser(credential.user);
78
        }
79
        await callbackBeforeRedirect(credential);
80
        if (redirect) {
81
            await this.redirectAfterLogin();
82
        }
83
    }
84
85
    public async signInAnonymously(
86
        redirect: boolean = true,
87
        callbackBeforeRedirect: (
88
            credential: auth.UserCredential | null,
89
        ) => Promise<void> | void = () => undefined,
90
    ): Promise<void> {
91
        await this.signInByProvider(
92
            this.authProvider.authAnonymous,
93
            redirect,
94
            callbackBeforeRedirect,
95
        );
96
    }
97
98
    public async signInViaEmail(
99
        redirect: boolean = true,
100
        callbackBeforeRedirect: (
101
            credential: auth.UserCredential | null,
102
        ) => Promise<void> | void = () => undefined,
103
    ): Promise<void> {
104
        await this.signInByProvider(
105
            this.authProvider.authEmail,
106
            redirect,
107
            callbackBeforeRedirect,
108
        );
109
    }
110
111
    public async signInViaFacebook(
112
        redirect: boolean = true,
113
        callbackBeforeRedirect: (
114
            credential: auth.UserCredential | null,
115
        ) => Promise<void> | void = () => undefined,
116
    ): Promise<void> {
117
        await this.signInByProvider(
118
            this.authProvider.authFacebook,
119
            redirect,
120
            callbackBeforeRedirect,
121
        );
122
    }
123
124
    public async signInViaGithub(
125
        redirect: boolean = true,
126
        callbackBeforeRedirect: (
127
            credential: auth.UserCredential | null,
128
        ) => Promise<void> | void = () => undefined,
129
    ): Promise<void> {
130
        await this.signInByProvider(
131
            this.authProvider.authGithub,
132
            redirect,
133
            callbackBeforeRedirect,
134
        );
135
    }
136
137
    public async signInViaGoogle(
138
        redirect: boolean = true,
139
        callbackBeforeRedirect: (
140
            credential: auth.UserCredential | null,
141
        ) => Promise<void> | void = () => undefined,
142
    ): Promise<void> {
143
        await this.signInByProvider(
144
            this.authProvider.authGoogle,
145
            redirect,
146
            callbackBeforeRedirect,
147
        );
148
    }
149
150
    public async signInViaPhone(
151
        redirect: boolean = true,
152
        callbackBeforeRedirect: (
153
            credential: auth.UserCredential | null,
154
        ) => Promise<void> | void = () => undefined,
155
    ): Promise<void> {
156
        await this.signInByProvider(
157
            this.authProvider.authPhone,
158
            redirect,
159
            callbackBeforeRedirect,
160
        );
161
    }
162
163
    public async signInViaTwitter(
164
        redirect: boolean = true,
165
        callbackBeforeRedirect: (
166
            credential: auth.UserCredential | null,
167
        ) => Promise<void> | void = () => undefined,
168
    ): Promise<void> {
169
        await this.signInByProvider(
170
            this.authProvider.authTwitter,
171
            redirect,
172
            callbackBeforeRedirect,
173
        );
174
    }
175
176
    /**
177
     * Handle sign out request
178
     */
179
    public async signOut(): Promise<void> {
180
        const currentUser = auth().currentUser;
181
182
        if (currentUser) {
183
            const providers = this.authProvider.getProvidersByUser(currentUser);
184
185
            for (const provider of providers) {
186
                await provider.handleSignOut();
187
            }
188
        }
189
        await this.redirectAfterSignOut();
190
    }
191
192
    public async updateUserData(user: User) {
193
        await this.authStorageProvider
194
            .getProvider()
195
            .updateStoredDataByUser(user);
196
    }
197
198
    protected async redirectAfterSignOut() {
199
        if (this.config.signInPage) {
200
            await this.router.navigate([this.config.signInPage]);
201
        }
202
    }
203
204
    protected async redirectAfterLogin() {
205
        if (this.config.afterSignInPage) {
206
            console.log("Redirect ", this.config.afterSignInPage);
207
            await this.router.navigate([this.config.afterSignInPage]);
208
        }
209
    }
210
211
    private subscribeUserChanges(): void {
212
        this.angularFireAuth.authState.subscribe((user: any) => {
213
            if (user) {
214
                if (this.userDataSubscription) {
215
                    this.userDataSubscription.unsubscribe();
216
                }
217
                this.userDataSubscription = this.authStorageProvider
218
                    .getProvider()
219
                    .subscribeUserDataFromStorageByFirebaseUser(user)
220
                    .subscribe(result => {
221
                        this._user.next(result);
222
                    });
223
            } else {
224
                // Logged out
225
                this._user.next(null);
226
            }
227
            if (!this._userInitialized.getValue()) {
228
                this._userInitialized.next(true);
229
            }
230
        });
231
    }
232
}
233